#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>

int main(int argc, char const *argv[]) // ./a.out  file1  file2
{
    if(argc != 3)
    {
        printf("本程序用法：%s <src> <dst>\n", argv[0]);
        exit(0);
    }

    // 1. 以只读模式打开源文件
    int fd1 = open(argv[1], O_RDONLY);
    if(fd1 == -1)
    {
        perror("打开失败"); // 如果发生错误，会自动在“打开失败”后面接上错误信息“：xxxx”
        exit(0);
    }

    // 2. 以只写模式打开目标文件
    int fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if(fd2 == -1)
    {
        fprintf(stderr, "打开%s失败：%s\n", argv[2], strerror(errno));
        exit(0);
    }

    // 3. 不断地从src读取字节，写入dst
    char buf[100];
    int nread, nwrite;
    while(1)
    {
        bzero(buf, 100);

        // 试图以字节流从文件fd1读取100个字节到buf
        while((nread=read(fd1, buf, 100)) == -1 && errno == EINTR); 

        if(nread == 0) // 读完了
            break;

        if(nread == -1) // 遇到错误
        {
            fprintf(stderr, "读取文件失败：%s\n", strerror(errno));
            exit(0);
        }

        int ntotal = 0;
        while(nread > 0)
        {
            // 试图以字节流的方式将buf中的nread个字节写入fd2文件中 
            while((nwrite=write(fd2, buf+ntotal, nread))==-1 && errno == EINTR); 

            if(nwrite == -1) // 遇到错误
            {
                fprintf(stderr, "写入文件失败：%s\n", strerror(errno));
                exit(0);
            }

            nread -= nwrite;
            ntotal+= nwrite;
        }
    }

    // 4. 释放相关资源
    close(fd1);
    close(fd2);

    return 0;
}
